#include <iostream>
#include <memory>
#include <thread>
#include <mutex>
#include <chrono>

struct Base
{
    Base() { std::cout << "  Base::Base()" << std::endl; }

    // NOTE: non-virtual destructor is ok here
    ~Base() { std::cout << "  Base::~Base()" << std::endl; }
};


struct Derived : public Base
{
    Derived() { std::cout << "  Derived::Derived()" << std::endl; }
    ~Derived() { std::cout << "  Derived::~Derived()" << std::endl; }
};


void thrd_func(std::shared_ptr<Base> p)
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::shared_ptr<Base> lp = p;
    {
        static std::mutex io_mutex;
        std::lock_guard<std::mutex> lk(io_mutex);
        std::cout << "local pointer in a thread:\n"
            << "  lp.get() = " << lp.get()
            << ",  lp.use_count() = " << lp.use_count() << "\n";
    
    }
}


int main()
{
    std::cout << "======================================" << std::endl;
    std::shared_ptr<Base> p = std::make_shared<Derived>();
    std::cout << "Created a shared Derived (as a pointer to Base)\n"
        << "  p.get() = " << p.get()
        << ",  p.use_count() = " << p.use_count() << "\n";

    std::cout << "======================================" << std::endl;
    std::thread t1(thrd_func, p), t2(thrd_func, p), t3(thrd_func, p);
    p.reset();

    std::cout << "Shared ownership between 3 threads and released\n"
        << "ownership from main:\n"
        << "  p.get() = " << p.get()
        << ",  p.use_count() = " << p.use_count() << "\n";

    t1.join();
    t2.join();
    t3.join();

    std::cout << "======================================\n\n" << std::endl;

    return 0;
}
